// 引入axios
import axios from 'axios'

// 引入element-message提示，单独引用
import { Message } from 'element-ui'

// 引入时间戳
import { getTimeOutKey, setTimeOutKey } from '@/utils/auth'

// 引入store
import store from '@/store'

// 引入路由
import router from '@/router'

const timeOutDuration = 5 * 60 * 60 * 1000
// 封装时间戳函数
function checkTimeOut() {
  // 获取旧时间戳
  const oldTime = getTimeOutKey()
  // 获取现在的时间
  const newTime = Date.now()
  // 两个时间相减，如果大于设置的规定时间，就代表超时登录
  // return newTime - oldTime >= timeOutDuration
  if (newTime - oldTime >= timeOutDuration) {
    return true
  } else {
    setTimeOutKey(Date.now())
    return false
  }
}

// 创建axios实例
const service = axios.create({
  baseURL: process.env.VUE_APP_BASE_API, // url = base url + request url
  // withCredentials: true, // send cookies when cross-domain requests
  timeout: 5000 // request timeout
})

// 请求拦截器
service.interceptors.request.use(
  config => {
    // 如果有token ，发请求时，在请求头中添加token
    if (store.getters.token) {
      // 判断时间戳超过
      if (checkTimeOut()) {
        // 1. 提示错误(还是会走响应拦截，所以已经有弹窗)
        // 2. 执行退出 action 清理数据
        store.dispatch('user/logout')
        // 3. 跳转页面
        router.push('/login')
        // 4. 停止当前请求
        return Promise.reject(new Error('登录已失效'))
      } else {
        // 携带token 注意Bearer和token之间的空格
        config.headers.Authorization = 'Bearer ' + store.getters.token
      }
    }
    // 一定要有返回值
    return config
  },
  err => {
    return Promise.reject(err)
  }
)

// 响应拦截器
// 第一个参数函数是用来处理网络层面的成功
// 第二个参数函数是用来处理网络层面的失败
service.interceptors.response.use(
  // 成功
  res => {
    // 这里是网络请求成功的部分，这里不一定是对的
    // 即使网络请求成功，也可能数据层面的失败，比如 手机号或密码错误
    // 解构服务器给我们传回的三个数据 message success data 处理数据
    // console.log(res)
    const { message, success, data } = res.data
    if (success) {
      // Message.success(message)
      return data
    } else {
      Message.error(message)
      // 固定写法，只有返回拒绝当前请求，才会走错误处理的函数，比如.then().catch()中的catch，或者try()catch()中的catch
      // 如果是返回的其他的数据，都是走成功函数，比如.then().catch()中的then，或者try()catch()中的try
      return Promise.reject(new Error(message))
    }
  },
  // 失败
  err => {
    console.log('这是网络层面的错误')
    // 这是网络层面的失败
    // 可能性很多，一般情况之前已经处理过了，就是弹出提示信息，并且reject 即可
    console.dir(err)
    // 下面是对其中一种特殊情况进行独立处理
    // 需要先判断之前的数据是否存在
    if (err.response && err.response.data && err.response.data.code === 10002) {
      // 这里就是token问题
      // 删除资料
      store.dispatch('user/logout')
      // 跳转页面
      router.push('/login')
    }
    // 这里是弹出错误提示，使用的是element-message的单独引用的方法
    Message.error(err.message)
    // 拒绝掉当前的请求 promise，如果在一个promise的中间
    // 想要当前 promise 马上报错，需要返回一个 Promise.reject()  reject就是拒绝的意思
    // 使用错误对象进行提示
    // 固定写法，只有返回拒绝当前请求，才会走错误处理的函数，比如.then().catch()中的catch，或者try()catch()中的catch
    // 如果是返回的其他的数据，都是走成功函数，比如.then().catch()中的then，或者try()catch()中的try
    return Promise.reject(new Error(err.message))
  }
)

// 暴露axios实例
export default service
